package org.wavetech.scrollingcascade.drawable;

import android.animation.ArgbEvaluator;
import android.animation.ValueAnimator;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.animation.DecelerateInterpolator;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import org.wavetech.scrollingcascade.R;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import java.io.IOException;

public class EditDrawable extends Drawable {

    private static final int def_solid_color = 0xffffffff;
    private static final int def_border_color = 0xffcccccc;
    private static final float def_border_width = getDensity() * 1.5f;
    private static final float def_dash_width = getDensity() * 4f;
    private static final float def_dash_gap = getDensity() * 2f;

    public static final int BORDER_STYLE_SOLID = 0;
    public static final int BORDER_STYLE_DASHED = 1;

    private int borderStyle;
    private float borderRadius;
    private float focusedBorderRadius;
    private int solidColor;
    private int focusedSolidColor;
    private float borderWidth;
    private float focusedBorderWidth;
    private int borderColor;
    private int focusedBorderColor;
    private float dashGap;
    private float focusedDashGap;
    private float dashWidth;
    private float focusedDashWidth;
    private float phase;
    private float focusedPhase;

    private Paint paint = new Paint();
    private float hotSpotX;
    private float hotSpotY;
    private ArgbEvaluator argbEvaluator = new ArgbEvaluator();
    private float[] intervals = new float[2];

    private float p = 0;

    private boolean hasBeenFocused;


    public EditDrawable() {
    }

    @Override
    public void draw(@NonNull Canvas canvas) {
        int width = canvas.getWidth();
        int height = canvas.getHeight();


        paint.setStyle(Paint.Style.FILL);
        paint.setColor((Integer) argbEvaluator.evaluate(p, solidColor, focusedSolidColor));

        float strokeWidth = borderWidth - (borderWidth - focusedBorderWidth) * p;
        float strokeOffset = strokeWidth / 2f;

        borderRadius = Math.min(borderRadius, height / 2f);
        focusedBorderRadius = Math.min(focusedBorderRadius, height / 2f);
        float radius = borderRadius - (borderRadius - focusedBorderRadius) * p;


        canvas.drawRoundRect(strokeOffset, strokeOffset, canvas.getWidth(), canvas.getHeight(), radius, radius, paint);


        paint.setStrokeWidth(strokeWidth);
        paint.setStyle(Paint.Style.STROKE);
        paint.setColor((Integer) argbEvaluator.evaluate(p, borderColor, focusedBorderColor));

        intervals[0] = dashWidth;
        intervals[1] = dashGap;
        if (dashWidth != focusedDashWidth) {
            intervals[0] = dashWidth - (dashWidth - focusedDashWidth) * p;
        }
        if (dashGap != focusedDashGap) {
            intervals[1] = dashGap - (dashGap - focusedDashGap) * p;
        }

        float phase = this.phase;
        if (this.phase != this.focusedPhase) {
            phase = phase - (phase - focusedPhase) * p;
        }

        if (borderStyle == BORDER_STYLE_DASHED) {
            paint.setPathEffect(new DashPathEffect(intervals, phase));
        } else {
            paint.setPathEffect(null);
        }
        canvas.drawRoundRect(strokeOffset, strokeOffset, canvas.getWidth() - strokeOffset, canvas.getHeight() - strokeOffset, radius, radius, paint);


//        if (p > 0 && p < 1) {
//            invalidateSelf();
//        }
    }

    @Override
    public void setAlpha(int alpha) {

    }

    @Override
    public void setColorFilter(@Nullable ColorFilter colorFilter) {

    }

    @Override
    public boolean getPadding(@NonNull Rect padding) {
        padding.left = 40;
        padding.right = 40;
        return true;
    }

    @Override
    public void inflate(@NonNull Resources r, @NonNull XmlPullParser parser, @NonNull AttributeSet attrs, @Nullable Resources.Theme theme) throws IOException, XmlPullParserException {
        super.inflate(r, parser, attrs, theme);
        TypedArray typedArray = r.obtainAttributes(attrs, R.styleable.EditDrawable);

        borderStyle = typedArray.getInt(R.styleable.EditDrawable_borderStyle, BORDER_STYLE_SOLID);
        borderRadius = typedArray.getDimension(R.styleable.EditDrawable_borderRadius, 0);
        focusedBorderRadius = typedArray.getDimension(R.styleable.EditDrawable_focusedBorderRadius, 0);
        solidColor = typedArray.getColor(R.styleable.EditDrawable_solidColor, def_solid_color);
        focusedSolidColor = typedArray.getColor(R.styleable.EditDrawable_focusedSolidColor, def_solid_color);
        borderWidth = typedArray.getDimension(R.styleable.EditDrawable_borderWidth, def_border_width);
        focusedBorderWidth = typedArray.getDimension(R.styleable.EditDrawable_focusedBorderWidth, def_border_width);
        borderColor = typedArray.getColor(R.styleable.EditDrawable_borderColor, def_border_color);
        focusedBorderColor = typedArray.getColor(R.styleable.EditDrawable_focusedBorderColor, def_border_color);
        dashGap = typedArray.getDimension(R.styleable.EditDrawable_dashGap, def_dash_gap);
        focusedDashGap = typedArray.getDimension(R.styleable.EditDrawable_focusedDashGap, dashGap);
        dashWidth = typedArray.getDimension(R.styleable.EditDrawable_dashWidth, def_dash_width);
        focusedDashWidth = typedArray.getDimension(R.styleable.EditDrawable_focusedDashWidth, dashWidth);
        phase = typedArray.getDimension(R.styleable.EditDrawable_phase, 0);
        focusedPhase = typedArray.getDimension(R.styleable.EditDrawable_focusedPhase, phase);

        typedArray.recycle();
    }

    @Override
    protected boolean onStateChange(int[] stateSet) {
//        for (int st : state) {
//            switch (st) {
//                case android.R.attr.state_focused:
//                    return true;
//                case android.R.attr.state_focused:
//                    return true;
//                case android.R.attr.state_pressed:
//                    return true;
//            }
//        }

        boolean pressed = false;
        boolean focused = false;

        for (int state : stateSet) {
            if (state == android.R.attr.state_focused) {
                focused = true;
            } else if (state == android.R.attr.state_pressed) {
                pressed = true;
            }
        }


        //返回true表示需要重新绘制
        return checkStatesHasChanged(focused, pressed);

        //return super.onStateChange(stateSet);
    }

    private boolean checkStatesHasChanged(boolean focused, boolean pressed) {
        if (this.hasBeenFocused == focused) return false;
        this.hasBeenFocused = focused;
        ValueAnimator animator = ValueAnimator.ofFloat(focused ? 0 : 1, focused ? 1 : 0);
        animator.setInterpolator(new DecelerateInterpolator());
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                p = ((float) animation.getAnimatedValue());
                invalidateSelf();
            }
        });
        animator.start();
        return true;
    }

    @Override
    public void setHotspot(float x, float y) {
        this.hotSpotX = x;
        this.hotSpotY = y;
    }

    @Override
    public boolean isStateful() {
        return true;
    }

    @NonNull
    @Override
    public int[] getState() {
        return super.getState();
    }

    @Override
    public int getOpacity() {
        return PixelFormat.OPAQUE;
    }

    private static float getDensity() {
        return Resources.getSystem().getDisplayMetrics().density;
    }
}
